import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/Addons.js';


export default class Viewer {

  public graphWorld!: THREE.Scene;
  public renderer!: THREE.WebGLRenderer;
  public camera!: THREE.PerspectiveCamera;
  public clock!: THREE.Clock;
  public orbitControls!: OrbitControls;
  public domElement!: HTMLElement

  constructor(dom: HTMLElement) {
    this.domElement = dom;
    this._initViewer();
  }

  _initRenderer() {
    this.renderer = new THREE.WebGLRenderer();
    // 设置渲染器像素比例
    this.renderer.setPixelRatio(window.devicePixelRatio);
    // 设置渲染器宽度，高度
    this.renderer.setSize(this.domElement.clientWidth, this.domElement.clientHeight);
    // 设置渲染器的
    this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
    this.renderer.toneMappingExposure = 1.0;
    // 开启阴影效果
    this.renderer.shadowMap.enabled = true;
    // 阴影效果类型为软类型
    this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;

    this.renderer.render(this.graphWorld, this.camera);
    this.domElement.append(this.renderer.domElement);

  }

  _initCamera() {
    this.camera = new THREE.PerspectiveCamera(75, this.domElement.clientWidth / this.domElement.clientHeight, 1, 2000);
    this.camera.position.y = 500
    this.orbitControls = new OrbitControls(this.camera)
  }

  _initScene() {
    this.graphWorld = new THREE.Scene();
  }

  // 更新dom大小
  _undateDom() {
    // 更新参数
    this.camera.aspect = this.domElement.clientWidth / this.domElement.clientHeight // 摄像机视锥体的长宽比，通常是使用画布的宽/画布的高
    this.camera.updateProjectionMatrix() // 更新摄像机投影矩阵。在任何参数被改变以后必须被调用,来使得这些改变生效
    this.renderer.setSize(this.domElement.clientWidth, this.domElement.clientHeight)
    this.renderer.setPixelRatio(window.devicePixelRatio) // 设置设备像素比
    var delta = this.clock.getDelta();
    this.orbitControls.update(delta);
  }

  // 渲染dom
  _readerDom() {

    this.renderer.render(this.graphWorld, this.camera);
  }


  _initViewer() {
    // 初始化相机
    this._initCamera();
    // 初始化场景
    this._initScene();
    // 初始化渲染器
    this._initRenderer();
    this.clock = new THREE.Clock();

    const animate = () => {
      requestAnimationFrame(animate)

      this._undateDom()
      this._readerDom()
    }

    animate()
  }

}